package edu.ncsu.csc.camera.com;
// for SPOT
import com.sun.squawk.util.StringTokenizer;
// for PC
//import java.util.StringTokenizer;
//import java.awt.image.BufferedImage;
//import javax.imageio.*;
//import java.io.*;

/**
 * A CMUCameraPacket that represents a raw video frame from the CMUCam2
 * @author Richard Pospesel
 * @author Douglas McClusky
 */

public class FPacket extends CMUCameraPacket
{
    public static final int ROWS = 144;
    public static final int COLUMNS = 352 / 2;

	private byte[][] red = new byte[COLUMNS][ROWS];
    private byte[][] green = new byte[COLUMNS][ROWS];
    private byte[][] blue = new byte[COLUMNS][ROWS];

    /**
     *
     * @return
     */
    public byte[][] getBlue() {
        return blue;
    }

    /**
     *
     * @return
     */
    public byte[][] getGreen() {
        return green;
    }

    /**
     * 
     * @return
     */
    public byte[][] getRed() {
        return red;
    }

    /**
     * Constructs an FPacket from red, green and blue pixel information
     * are 172 columns by 144 rows.  For display purposes columns are doubled, creating a 352 x 144 picture
     * @param red [COLUMNS][ROWS]
     * @param green [COLUMNS][ROWS]
     * @param blue [COLUMNS][ROWS]
     */
    public FPacket(byte[][] r, byte[][] g, byte[][] b) {
        if (r.length !=ROWS || r[0].length != COLUMNS || g.length !=ROWS || g[0].length != COLUMNS || b.length !=ROWS || b[0].length != COLUMNS) {
            throw new IllegalArgumentException("Frames must be 352 x 144 pixels");
        }
        red = r;
        green = g;
        blue = b;
        super.type = super.F_PACKET;
    }
    
    /**
     * Type F data packet format: <br>
     * 1 - new frame followed by X size and Y size <br>
     * 2- new col <br>
     * 3 - end of frame RGB (CrYCb) ranges from 16-240 <br>
     * 1 xSize ySize 2 r g b r g b ... r g b r g b 2 r g b r g b ... r g b r g b 3
     * @param str - String formatted as the SF command from CMUCam2 documentation (specified above).
     * @throws java.lang.IllegalArgumentException
     */
    public FPacket (String str) throws IllegalArgumentException
	{
        super.type = super.F_PACKET;
        if (!str.startsWith("1") || !str.endsWith("3")) {
            throw new IllegalArgumentException("String does not contain beginning and end marks of frame.");
        }
		StringTokenizer st = new StringTokenizer(str, " ");
        st.nextToken();
        byte value;
        for (int y=0; y<ROWS; y++) {
            if (!"2".equals(st.nextToken())) {
                throw new IllegalArgumentException("Malformed frame row: " + y);
            }
            for (int x=0; x<COLUMNS; x++) {
                //red
                value = Byte.parseByte(st.nextToken());
                if (value<16 || value>240) {
                    throw new IllegalArgumentException("Illegal RGB value, " + value + ", on row: " + y + ", column: " + 3*x/2);
                }
                red[x][y] = value;
                //green
                value = Byte.parseByte(st.nextToken());
                if (value<16 || value>240) {
                    throw new IllegalArgumentException("Illegal RGB value, " + value + ", on row: " + y + ", column: " + 3*x/2+1);
                }
                green[x][y] = value;
                //blue
                value = Byte.parseByte(st.nextToken());
                if (value<16 || value>240) {
                    throw new IllegalArgumentException("Illegal RGB value, " + value + ", on row: " + y + ", column: " + 3*x/2+2);
                }
                blue[x][y] = value;
            }
        }
	}

	/**
     * Constracts an FPacket from the output of FPacket.toByteArray()
     * @param in
     */
    public FPacket(byte[] in) {
        super.type = super.F_PACKET;
        for (int y=0; y<ROWS; y++) {
            for (int x=0; x<COLUMNS; x++) {
                red[x][y]   = in[3*x*y+0];
                green[x][y] = in[3*x*y+1];
                blue[x][y]  = in[3*x*y+2];
            }
        }
    }

    /**
     * Displays this FPacket as the String returned by the CMUCam2
     * @return
     */
    public String toString()
	{
		String str = "1 ";
        for (int y=0; y<ROWS; y++) {
            str = str + "2 ";
            for (int x=0; x<COLUMNS; x++) {
                str = str + red[x][y] + " " + green[x][y] + " " + blue[x][y] + " ";
            }
        }
        return str+ "3 ";
	}

    /**
     * A byte array representation of this FPacket for communication purposes
     * @return
     */
    public byte[] toByteArray() {
        byte[] out = new byte[3*ROWS*COLUMNS];
        for (int y=0; y<ROWS; y++) {
            for (int x=0; x<COLUMNS; x++) {
                out[3*x*y+0] = red[x][y];
                out[3*x*y+1] = green[x][y];
                out[3*x*y+2] = blue[x][y];
            }
        }
        return out;
    }

/* Comment out this line for HostApplication
    /**
     * Write this FPacket to a .png file using BufferedImage (only available for HostApplications.
     * Comment out this method for SPOT Applications
     * @param name - the file name.  Creates a picture file named "[name].png"
     * @throws IOException
     */

/* Comment out this line for HostApplication

    public void toFile(String name) throws IOException
	{
		BufferedImage image = new BufferedImage(width * 2, height, BufferedImage.TYPE_INT_RGB);
		for(int h = 0; h < ROWS; h++)
		{
			for(int w = 0; w < COLUMNS * 2; w++)
			{
				// this expects an int for red, green and blue
				// in java, byte order is Most Significant Byte first
				image.setRGB(w, h, (red[w/2][h] << 16) +(green[w/2][h] << 8) + (blue[w/2][h]));
			}
		}
		File output = new File(name + ".png");  
		ImageIO.write(image, "png", output); 
	}
 //*/
}